package bomberman.modelo.mapa;

import java.util.List;

import org.jdom2.Element;

import bomberman.modelo.armas.Molotov;
import bomberman.modelo.armas.Proyectil;
import bomberman.modelo.armas.ToleTole;
import bomberman.modelo.items.BombaToleTole;
import bomberman.modelo.items.HabanoChala;
import bomberman.modelo.items.Timer;
import bomberman.modelo.obstaculos.BloqueAcero;
import bomberman.modelo.obstaculos.BloqueCemento;
import bomberman.modelo.obstaculos.BloqueLadrillo;
import bomberman.modelo.personajes.Bombita;
import bomberman.modelo.personajes.Cecilio;
import bomberman.modelo.personajes.LopezReggae;
import bomberman.modelo.personajes.LopezReggaeAlado;

public class Mapa {
  private Casillero[][]     casilleros;
  private final Direccion[] direcciones = {Direccion.NOROESTE, Direccion.NORTE, Direccion.NORESTE, Direccion.OESTE,
    Direccion.ESTE, Direccion.SUROESTE, Direccion.SUR, Direccion.SURESTE};
  private Salida            salida;
  
  public Mapa(int tamanioMapa, Posicion posicionSalida) {
    this.casilleros = new Casillero[tamanioMapa][tamanioMapa];
    this.crearCasilleros(posicionSalida);
  }
  
  public Mapa(Element eMapa, Nivel nivel) {
    int tamanio = Integer.parseInt(eMapa.getAttributeValue("Tamanio"));
    Element eSalida = eMapa.getChild("Salida");
    Element eUbicacion = eSalida.getChild("Ubicacion");
    
    int posXSalida = Integer.parseInt(eUbicacion.getAttributeValue("X"));
    int posYSalida = Integer.parseInt(eUbicacion.getAttributeValue("Y"));
    
    Posicion posicionSalida = new Posicion(posXSalida, posYSalida);
    this.casilleros = new Casillero[tamanio][tamanio];
    this.crearCasilleros(posicionSalida);
    Posicion pos;
    int x, y;
     List<Element> listaElementos = eMapa.getChildren();
    
    // el primer hijo de mapa es la salida, ya esta contemplada
    for (int i = 1; i < listaElementos.size(); i++) {
      Element element = listaElementos.get(i);
      Element nodoUbicacion = element.getChild("Ubicacion");
      
      x = Integer.parseInt(nodoUbicacion.getAttributeValue("X"));
      y = Integer.parseInt(nodoUbicacion.getAttributeValue("Y"));
      
      pos = new Posicion(x, y);
      
      Casillero casillero = getCasillero(pos);
      
      if (element.getName().equals("LopezReggaeAlado")) {
    	  nivel.agregarEnemigo(LopezReggaeAlado.recuperar(element, casillero));
      }if (element.getName().equals("Proyectil")){
  	  Proyectil.recuperar(element, casillero);
      }else if (element.getName().equals("BloqueAcero")) {
    	  BloqueAcero.recuperar(element, casillero);
      }else if (element.getName().equals("BloqueCemento")) {
    	  BloqueCemento.recuperar(element, casillero);
      }else if (element.getName().equals("BloqueLadrillo")) {
    	  BloqueLadrillo.recuperar(element, casillero);
      }else if (element.getName().equals("Cecilio")) {
    	  nivel.agregarEnemigo(Cecilio.recuperar(element, casillero));
      }else if (element.getName().equals("LopezReggae")) {
    	  nivel.agregarEnemigo(LopezReggae.recuperar(element, casillero));
      }else if (element.getName().equals("Bombita")) {
    	  nivel.setBombita(Bombita.recuperar(element, casillero));
      }else if (element.getName().equals("Proyectil")){
    	  Proyectil.recuperar(element, casillero);
      }else if (element.getName().equals("ToleTole")){
    	  ToleTole.recuperar(element, casillero);
      }else if (element.getName().equals("Molotov")){
    	  Molotov.recuperar(element, casillero);
      }else if (element.getName().equals("Timer")){
    	  Timer.recuperar(casillero);
      }else if (element.getName().equals("ItemHabanoChala")){
    	  HabanoChala.recuperar(casillero);
      }else if (element.getName().equals("ItemToleTole")){
    	  BombaToleTole.recuperar(casillero);
      }
    }
  }
  
  public Salida getSalida() {
    return this.salida;
  }
  
  private void crearCasilleros(Posicion posicionSalida) {
    for (int fila = 0; fila < this.casilleros.length; fila++) {
      for (int columna = 0; columna < this.casilleros.length; columna++) {
        Casillero casillero;
        if ((fila == posicionSalida.getVertical()) && (columna == posicionSalida.getHorizontal())) {
          casillero = new Salida(new Posicion(fila, columna), null, null, null);
          this.salida = (Salida) casillero;
        } else {
          casillero = new Casillero(new Posicion(fila, columna), null, null, null);
        }
        this.casilleros[fila][columna] = casillero;
      }
    }
    for (int fila = 0; fila < this.casilleros.length; fila++) {
      for (int columna = 0; columna < this.casilleros.length; columna++) {
        int indice = 0;
        for (int vecinoVertical = -1; vecinoVertical <= 1; vecinoVertical++) {
          for (int vecinoHorizontal = -1; vecinoHorizontal <= 1; vecinoHorizontal++) {
            if ((vecinoHorizontal == 0) && (vecinoVertical == 0)) {
              continue;
            }
            if ((((fila + vecinoVertical) >= 0) && ((fila + vecinoVertical) < this.casilleros.length))
              && (((columna + vecinoHorizontal) >= 0) && ((columna + vecinoHorizontal) < this.casilleros.length))) {
              this.casilleros[fila][columna].setVecino(this.direcciones[indice],
                this.casilleros[fila + vecinoVertical][columna + vecinoHorizontal]);
            }
            indice++;
          }
        }
      }
    }
  }
  
  public Casillero getCasillero(Posicion posicion) {
    return this.casilleros[posicion.getVertical()][posicion.getHorizontal()];
  }
  
  public int getCantidadCasilleros() {
    int tamanio = this.casilleros.length;
    
    return tamanio * tamanio;
  }
  
  public Element serializar() {
    Element eMapa = new Element("Mapa");
    int tamanioMapa = (int) Math.sqrt(this.getCantidadCasilleros());
    eMapa.setAttribute("Tamanio", String.valueOf(tamanioMapa));
    Element eSalida = new Element("Salida");
    eSalida.setContent(this.getSalida().serializarUbicacion());
    eMapa.setContent(eSalida);
    Element eContenido = new Element("Contenido");
    Posicion posTemporal;
    Casillero casTemporal;
    for (int i = 0; i < this.casilleros.length; i++) {
      for (int j = 0; j < this.casilleros.length; j++) {
        posTemporal = new Posicion(i, j);
        casTemporal = this.getCasillero(posTemporal);
        eContenido = casTemporal.serializarContenidoBajo();
        if (eContenido != null) {
          eMapa.addContent(eContenido);
        }
        eContenido = casTemporal.serializarContenidoMedio();
        if (eContenido != null) {
            eMapa.addContent(eContenido);
          }
        eContenido=casTemporal.serializarContenidoAlto();
        if (eContenido != null) {
            eMapa.addContent(eContenido);
          }
      }
    }
    return eMapa;
  }
}
